#include "TouchpadMonitor.h"
#include <iostream>

#pragma comment(lib, "hid.lib")

namespace TouchpadUtils {
const std::wstring WNDNAME = L"MSG_ONLY_WINDOW_CLASS";
WNDCLASSEX g_wndClass;

TouchpadMonitor::TouchpadMonitor()
{
}

TouchpadMonitor::~TouchpadMonitor()
{
}

TouchpadMonitor* TouchpadMonitor::GetInstance()
{
	static TouchpadMonitor instance;
	return &instance;
}

bool TouchpadMonitor::Init()
{
	MSG msg;
	// 创建一个隐藏的窗口
	hWnd = TouchpadMonitor::GetInstance()->Create(WndProc);
	if (hWnd == nullptr) {
		return false;
	}
	ShowWindow(hWnd, false);
	UpdateWindow(hWnd);
	// 是否需要检测有无精度触摸板
	SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
	// 注册触摸板设备事件
	RegisterTouchpadInput();

	// 消息循环
	while (GetMessage(&msg, nullptr, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	UnRegisterWndClass();
	return true;
}

void TouchpadMonitor::UnInit()
{
	if (hWnd == nullptr) {
		return;
	}
	PostMessage(hWnd, WM_CLOSE, 0, 0);
}

HWND TouchpadMonitor::Create(WNDPROC wndProc)
{
	if (!RegisterWndClass(wndProc)) {
		return nullptr;
	}
	HWND hWnd = CreateWindowEx(0, WNDNAME.c_str(), L"MSG_ONLY_WINDOW", 0, 0, 0, 0, 0,
		HWND_MESSAGE, nullptr, nullptr, nullptr);
	return hWnd;
}

bool TouchpadMonitor::RegisterWndClass(WNDPROC wndProc)
{
	g_wndClass.cbSize = sizeof(WNDCLASSEX);
	g_wndClass.lpfnWndProc = wndProc;
	g_wndClass.lpszClassName = WNDNAME.c_str();
	return RegisterClassEx(&g_wndClass);
}

bool TouchpadMonitor::UnRegisterWndClass() const
{
	if (!UnregisterClass(WNDNAME.c_str(), GetModuleHandle(0))) {
		return false;
	}
	return true;
}

// 注册监控触摸板的输入设备
bool TouchpadMonitor::RegisterTouchpadInput() const
{
	RAWINPUTDEVICE dev;
	dev.usUsagePage = HID_USAGE_PAGE_DIGITIZER;
	// 符合HID标准的触控板
	dev.usUsage = HID_USAGE_DIGITIZER_TOUCH_PAD;
	dev.dwFlags = RIDEV_INPUTSINK;
	dev.hwndTarget = hWnd;

	return RegisterRawInputDevices(&dev, 1, sizeof(RAWINPUTDEVICE));
}

void TouchpadMonitor::HandleRawInput(WPARAM* wParam, LPARAM* lParam)
{
	static int iCount = 0;
	std::cout << "enter HandleRawInput " << ++iCount << std::endl;

	// 根据原始输入数据，解析出触摸板事件：TouchUp、TouchDown、TouchMove

}

LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_INPUT:
			TouchpadMonitor::GetInstance()->HandleRawInput(&wParam, &lParam);
			break;
		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}
	return 0;
}
}